En este post veremos como usar un tipo de *VPN* de capa 4 y que todo el tráfico hacia internet que salga de nuestra computadora personal vaya **a través** de una VPN propia con [wireguard](https://www.wireguard.com/).

![vpn-gateway.png](/static/imgs/posts/thumb_vpn-gateway.png)
[<- Tamaño original](/static/imgs/posts/vpn-gateway.png)

Es como una evolución [de uno anterior](accediendo-a-equipos-de-casa-mediante-vpn-wireguard) donde se usaba un servidor remoto como **compuerta de entrada** para conectar equipos mediante VPN. En este caso usaremos el mismo servidor para también ser una **compuerta de salida** hacia internet.

**Aviso:** Este post está dividido en 2 secciones:

1. [La primera](#1-redes-de-computadoras-y-como-funcionan-las-vpn-a-grandes-rasgos) por si te interesa saber un poco como funcionan las VPN y las redes TCP/IP en general.
2. [La segunda](#2-configurando-la-vpn) si solo quieres ver un ejemplo de los pasos necesarios para configurar una VPN con salida hacia internet.

## 1. Redes de computadoras y cómo funcionan las VPN a grandes rasgos

Las [redes privadas virtuales](https://es.wikipedia.org/wiki/Red_privada_virtual) *VPN* permiten extender la conexión entre computadoras gracias a su flexibilidad, cifrado y "resistencia a bloqueos" se pueden establecer comunicaciones con mejor protección contra sistemas de vigilancia o filtración. Pero ¿cómo funcionan las VPN de capa 4?

### Una analogía del modelo TCP/IP

El modelo de conexiones de red [TCP/IP](https://es.wikipedia.org/wiki/Modelo_TCP/IP) es una forma de mandar/recibir mensajes alrededor del mundo entre computadoras, este tiene sus complejidades pero la forma en que funciona se asemeja al servicio postal.

![servicio postal](/static/imgs/posts/servicio-postal.jpg)

1. Delia escribe un mensaje para Mijael, lo pone en un sobre y escribe en el sobre información para que el mensaje llegue a Mijael.

    - **De**: El nombre del remitente. `Delia Gomez`
    - **Para**: El nombre del destinatario. `Mijael Torres`
    - **Dir.**: La dirección de Mijael. `Claveles #192. Salta - Argentina`

2. Delia lleva el sobre a una oficina postal.
3. La oficina postal comprueba si la **dirección** de Mijael está en su alcance inmediato, como no está, determina cual es la siguiente oficina postal más cercana hacia la dirección de Mijael.
4. La oficina postal despacha el mensaje en un camión o medio de transporte para que lleve el sobre a la siguiente oficina postal.
5. El sobre llega a la oficina postal 2 y esta repite los pasos 3 y 4 de ser necesario.
6. En algún momento los sobres llegan a la oficina postal inmediatamente mas cercana a la dirección de Mijael (La oficina postal N), y esta le entrega el sobre a un cartero para que lo reciba Mijael.
7. El cartero lee la **dirección** de Mijael en el sobre y sale hacia esta dirección para entregarle el sobre.
8. Mijael atiende al cartero que le entrega el sobre, lee que el mensaje viene de Delia Gomez, lo abre y lee el mensaje.

En resumen, el sobre tiene la suficiente metainformación para que cada oficina postal o cartero sepa hacia dónde se debe hacer llegar el mensaje. Las oficinas postales pueden usar **cualquier medio de transporte** para hacer llegar el mensaje, lo importante es que determinarán el camino óptimo para que el sobre llegué a la **dirección** y **destinatario final**.

### Volviendo al modelo TCP/IP

Al igual que el sistema de servicio postal, el modelo TCP/IP es una serie de protocolos y tecnologías que permiten que datos lleguen desde una dirección, el objetivo final es el mismo pero la forma de hacerlo y terminología difiere, más o menos:

<table>
    <tr>
        <td>Servicio Postal</td>
        <td>TCP/IP</td>
        <td>Capa TCP/IP</td>
    </tr>
    <tr>
        <td>Mensaje</td>
        <td>Datos finales</td>
        <td>4 (Aplicación)</td>
    </tr>
    <tr>
        <td>Sobre</td>
        <td>Paquetes de datos</td>
        <td>3 (Transporte)</td>
    </tr>
    <tr>
        <td>Oficina Postal</td>
        <td>Router</td>
        <td>2 (Internet)</td>
    </tr>
    <tr>
        <td>Dirección en el sobre</td>
        <td>Dirección IP destino</td>
        <td>2 (Internet)</td>
    </tr>
    <tr>
        <td>Dirección de otras direcciones postales</td>
        <td>Direcciones IP de otros routers</td>
        <td>2 (Internet)</td>
    </tr>
    <tr>
        <td>Camión o medio de transporte</td>
        <td>Medio físico de transporte</td>
        <td>1 (Acceso al medio)</td>
    </tr>
</table>

El modelo TCP/IP tiene muchos más elementos y es más sofisticado porque provee también formas de verificar que el mensaje llega sin alteraciones (TCP), de asegurarse de que el destinatario y el remitente sean los correctos (IP destino recibirá siempre el mensaje y se sabrá que viene de IP origen), de encontrar el camino óptimo. etc. Y esto lo hace gracias a diferentes protocolos. Las 4 capas TCP/IP actúan una independientemente de la otra mediante encapsulamiento.

### ¿Qué tiene que ver con VPN?

Imaginémos que Delia quiere enviar un mensaje a Diana de tal forma que el servicio postal no sepa que el remitente es Delia. Una forma de hacerlo es colocar en el contenido del mensaje indicaciones para Mijael que le digan que debe enviar otro mensaje a Diana, el contenido del mensaje tendrá algo como:

> Querido Mijael, por favor envía lo siguiente a Diana de mi parte pero hazlo en otro sobre que venga de ti. La **dirección de Diana** es "Las Palmas #816 - Chiclayo, Perú". Este el mensaje: ...

Si Mijael sigue las instrucciones, escribirá otro mensaje o usará este mismo y lo pondrá en **otro sobre** con la dirección de Diana y lo llevará a la oficina postal mas cercana con él como remitente. De esta manera la oficina postal no sabrá que el mensaje original viene de Delia.

Delia y Mijael podrían ir más lejos y proteger el mensaje escribiendo en otro idioma o codificado de forma que si alguien no autorizado abre el sobre, no pueda entenderlo, es decir aplicarían algún tipo de **cifrado**.

#### Ocultando el remitente en TCP/IP

Los paquetes de datos de red son una serie bits (1 y 0) acomodados en cierto orden de manera que los equipos de red como los *routers* los revisen y sepan dónde enviarlos. Los *routers* revisarán ciertas secciones del paquete para determinar el origen y destino de los paquetes. Luego revisarán secciones de bits diferentes para determinar a qué puerto de la computadora destino irán,cúal es el origen y tomarán en cuenta otras partes del paquete para hacer verificaciones adicionales.

Repasemos un poco una parte de un paquete de datos UDP+IP, [UDP](https://es.wikipedia.org/wiki/Protocolo_de_datagramas_de_usuario) es un protocolo de transporte que permite transmisión de datagramas de forma rápida.

![udp-ip1](/static/imgs/posts/upd-ip1.jpg)

Imagen modificada de [Irwin, David & Slay. Extracting Evidence Related to VoIP Calls.](https://www.researchgate.net/publication/221352750_Extracting_Evidence_Related_to_VoIP_Calls)

La sección del paquete que dice **Payload** son los datos o mensaje y al igual que hizo Delia, se puede enviar en el mensaje mismo otra IP como destinatario final. Algo mas o menos así:

![udp-ip2](/static/imgs/posts/upd-ip2.jpg)

El encapsulamiento permite incrustar en el payload del mensaje otras direcciones, puertos y datos. Como si se tratase de un paquete dentro de uno o más paquetes. Las VPN como wireguard van más lejos y usan protocolos y algoritmos de cifrado para que todo el tráfico dentro del payload solo sea reconocible por **miembros autorizados**.

Para que una VPN funcione, se necesitan programas que hagan como Mijael, es decir, revisen el mensaje (*payload*) y busquen si se trata de un mensaje que en realidad va para otra dirección que no esté declarada en las cabeceras *Source Address, Destination Address* originales de los paquetes UDP+IP.

Esto es encapsular paquetes dentro de otros paquetes, y si el programa detecta que este paquete es para otro destinatario entonces lo reenviará para que el resto de la red se encargue de hacerlo llegar al destino real. Entonces, en la práctica tenemos una **red virtual**. Si se agrega cifrado y otras medidas de seguridad, se tiene una red privada virtual (*VPN*) mucho mas segura, flexible y resistente a posibles bloqueos o vigilancia indiscriminada por parte de cualquier equipo dentro de la red.

----

## 2. Configurando la VPN

Ahora configuraremos un servidor remoto y una computadora cliente para crear una VPN con wireguard, luego haremos que la computadora cliente salga a internet a través de la conexión VPN hacia el servidor y que el servidor redirija los paquetes del cliente hacia el internet a modo de compuerta de salida o *internet gateway*.

### Lo necesario

Para el resto de este tutorial se asume que se tiene un servidor y computadora con GNU/Linux, para este tutorial se usa debian 11 en ambos lados, sin embargo wireguard también funciona en otros S.O. como Windows. Lo que si es necesario es tener acceso a un servidor remoto que tenga conexión a internet.

![vpn-gateway.png](/static/imgs/posts/thumb_vpn-gateway.png)
[<- más grande](/static/imgs/posts/vpn-gateway.png)

El anterior es un diagrama de un caso posible de uso donde hay un servidor web, lo importante es la parte de conexión por VPN y salida por NAT. La implementación siguiente es sólo para configurar la conexión por VPN y uso del servidor como *internet gateway*.

### Poniendo servidor y pc en la misma VPN

Para este primer paso puedes revisar el post [Accediendo a equipos de casa mediante VPN wireguard](accediendo-a-equipos-de-casa-mediante-vpn-wireguard) como otro ejemplo. Pero resumiendo las configuraciones las haremos como en el diagrama
anterior:

  * Servidor
    * IP: 10.50.0.1
	* Puerto: 51830
	* Gateway y NAT
  * Cliente
    * IP: 10.50.0.2
	* Puerto: 51830

Ahora declararemos los archivos de configuración de wireguard.

#### wireguard.conf en el Servidor 

    :::conf
    [Interface]
    PrivateKey = YPrreNTz7...
    ListenPort = 51830
    
    # peer pc
    [Peer]
    PublicKey = yQ2po/Rl3...
    AllowedIPs = 10.50.0.2/32

En el servidor declaramos también el *peer* de la pc 

#### wireguard.conf en el cliente

    :::conf
    [Interface]
    PrivateKey = cMNHAA7vY6k9X...
    ListenPort = 51830
    
    # peer servidor (gateway server)
    [Peer]
    PublicKey = BTg7lbZWQ...
    Endpoint = <IP o dominio del servidor>:51830
    AllowedIPs = 0.0.0.0/0
    PersistentKeepalive = 15

#### Interfaz de red, masquerading y NAT en el servidor

Wireguard es tan conveniente que nos permite dedicar una interfaz de red a la VPN. El siguiente script en bash, nos ayuda a crear la interfaz de red para wireguard (`wg0`), habilitar *NAT* (Network Address Translation) y agregar reglas de ruteo para que cuando se reciba tráfico en la interfaz `wg0` este pueda ser redirigido hacia internet aplicando *NAT masquerading*.

    :::bash
    #!/bin/bash
	# levantar.sh

    WG=wg
    conf_file=./wireguard.conf
    interface=wg0
    address=10.50.0.1
    nw_cidr=10.50.0.0/24
    nw_interface=eth0 # interfaz por la que el servidor sale hacia internet

    # Configurando interfaces de red
    ip link del dev $interface 2>/dev/null || true
    ip link add $interface type wireguard
    ip addr add $address/24 dev $interface
    ip link set $interface up
    # usando archivo de config
    $WG setconf $interface $conf_file
    $WG show

    # Habilitando masquerading
    echo "net.ipv4.ip_forward = 1" > /etc/sysctl.d/70-wireguard-routing.conf
    sysctl -p /etc/sysctl.d/70-wireguard-routing.conf -w

    # Agrega la regla NAT a la cadena POSTROUTING para tráfico ya filtrado por iptables
    iptables -t nat -A POSTROUTING -s $nw_cidr -o $nw_interface -j MASQUERADE

    # mtu
    ip link set mtu 1378 up dev $interface
	exit 0

Ejecutaremos el script con privilegios de superusuario. `sudo bash levantar.sh`. Con `ip a` se debería mostrar una interfaz `wg0` existente y con `sudo iptables -t nat -L -v`:

    Chain POSTROUTING (policy ACCEPT 0 packets, 0 bytes)
     pkts bytes target     prot opt in     out     source               destination
        0     0 MASQUERADE  all  --  any    eth0    10.50.0.0/24         anywhere
		
#### Interfaz de red, reglas para salir a internet a través de la conexión VPN

    :::bash
    #!/bin/bash

    # levantar.sh
    WG=wg
    conf_file=./wireguard.conf
    interface=wg0
    address=10.50.0.2

    # Configurando interfaces de red
    ip link del dev $interface 2>/dev/null || true
    ip link add $interface type wireguard
    ip addr add $address/24 dev $interface
    ip link set $interface up

    # usando archivo de config wireguard.con
    $WG setconf $interface $conf_file
    $WG show

    # mtu
    ip link set mtu 1420 up dev $interface

    # fwmark agrega una marca a los paquetes de wireguard para que
    # se manden a una tabla de ruteo alternativa, en este caso 51820
    wg set $interface fwmark 51820
    wg setconf $interface /dev/fd/63
    ip link set mtu 1420 up dev $interface

    # se establece la ruta por defecto hacia la tabla de ruteo 51820
    ip -4 route add 0.0.0.0/0 dev $interface table 51820
    # los paquetes que no tienen la marca fwmark iran a esta tabla alternativa 
    ip -4 rule add not fwmark 51820 table 51820
    # Se permiten a los paquetes sin la marca, usar la tabla de ruteo principal
    ip -4 rule add table main suppress_prefixlength 0

    sysctl -q net.ipv4.conf.all.src_valid_mark=1
	nft -f /dev/fd/63

    exit 0

Ahora ejecutamos el script con `sudo bash levantar.sh`. Para probar que la conexión con el servidor funciona, `ping 10.50.0.1` debería funcionar.

Para comprobar que el tráfico a internet va por VPN a través del servidor, se puede hacer `traceroute 1.1.1.1` que debería mostrar el primer salto como la IP del servidor en la VPN.

    traceroute to 1.1.1.1 (1.1.1.1), 30 hops max, 60 byte packets
     1  10.50.0.1 (10.50.0.1)  224.311 ms  224.063 ms  223.958 ms
     2  * * *
     3  51.12.176.255 (51.12.176.255)  224.546 ms  224.427 ms  224.305 ms
     4  195.12.20.173 (195.12.20.173)  225.083 ms  225.010 ms  225.157 ms
     5  195.22.0.8 (195.22.0.8)  228.603 ms  228.657 ms  228.534 ms
     6  170.4.122.195.in-addr.arpa (195.22.0.8)  228.520 ms  240.060 ms  239.866 ms
     7  1.1.1.1.in-addr.arpa (1.1.1.1)  227.739 ms  228.523 ms  228.461 ms
	 
## Conclusiones

Existen muchos servicios que permiten salir a internet a través de VPN, a pesar de que muchos son buenos hay otros que no son garantizados y también son poco transparentes. Esta solución nos permite tener un mayor control.

Ahora podemos navegar por internet usando el servidor como puerta de acceso, además el tráfico va cifrado y sobre una red que podemos extender a nuestra conveniencia. Por ejemplo agregando más equipos o uniéndose a otras redes. Se puede agregar más seguridad por ejemplo sobre el tráfico DNS como se ve en los enlaces adicionales.

Espero este tutorial te haya ayudado a entender mejor cómo funcionan internamente las redes dentro de otras redes ;)

## Enlaces de interés

* [A little bit about how VPN actually works… – The 4-Layer TCP/IP Stack + TLS](https://www.kiloroot.com/a-little-bit-about-how-vpn-actually-works-the-4-layer-tcpip-stack-tls/). Este artículo también explica como funcionan las VPN de forma mas de detallada.
* [Using the VPN as the default gateway](https://ubuntu.com/server/docs/wireguard-vpn-defaultgw). Usé ese post para configurar el mecanismo del default gateway en el cliente y el servidor.
* [Configure NAT masquerading in iptables](https://www.adamintech.com/configure-nat-masquerading-in-iptables/). Sobre `iptables` y *masquerading*.
